package testes;

import static org.junit.Assert.*;

import org.junit.Test;

import simulacao.TabelaPayoffs;
import estrategias.*;

public class TesteEstrategias {
	
	@Test
	public void testaEstrategiaSempreCooperar() {
		EstrategiaSempreCooperar estr = new EstrategiaSempreCooperar();
		estr.setJogadaAnteriorAdversario(0);
		assertTrue(estr.getJogada()==0);
		estr.setJogadaAnteriorAdversario(1);
		assertTrue(estr.getJogada()==0);
	}
	
	@Test
	public void testaEstrategiaSempreObstar() {
		EstrategiaSempreObstar estr = new EstrategiaSempreObstar();
		estr.setJogadaAnteriorAdversario(0);
		assertTrue(estr.getJogada()==1);
		estr.setJogadaAnteriorAdversario(1);
		assertTrue(estr.getJogada()==1);
	}
	
	@Test
	public void testaEstrategiaAleatoria() {
		EstrategiaAleatoria estr = new EstrategiaAleatoria();
		estr.setProbCooperar(0.0);
		estr.setJogadaAnteriorAdversario(0);
		assertTrue(estr.getJogada()==1);
		estr.setProbCooperar(1.0);
		estr.setJogadaAnteriorAdversario(0);
		assertTrue(estr.getJogada()==0);
		estr.setProbCooperar(0.0);
		estr.setJogadaAnteriorAdversario(1);
		assertTrue(estr.getJogada()==1);
		estr.setProbCooperar(1.0);
		estr.setJogadaAnteriorAdversario(1);
		assertTrue(estr.getJogada()==0);
	}
	
	@Test
	public void testaAleatoriedade() {
		int[] estrategia = {0, 0};
		int total = 1000000;
		double m = 0.5;
		EstrategiaAleatoria estr = new EstrategiaAleatoria();
		estr.setProbCooperar(m);
		for (int i = 0; i < total; i++) {
			estrategia[estr.getJogada()]++;
		}
		assertTrue(((double)estrategia[0]/total)>(m-0.01) && ((double)estrategia[0]/total)<(m+0.01));
		assertTrue(((double)estrategia[1]/total)>(1.0-m-0.01) && ((double)estrategia[1]/total)<(1.0-m+0.01));
	}
	
	@Test
	public void testaEstrategiaPunicaoPermanente(){
		int total = 100;
		double rand;
		int esperado = 0;
		EstrategiaPunicaoPermanente estr = new EstrategiaPunicaoPermanente();
		estr.setJogadaAnteriorAdversario(0);
		for (int i = 0; i < total; i++) {
			rand = Math.random();
			if (rand < 0.05){
				estr.setJogadaAnteriorAdversario(1);
				esperado = 1;
			}
			assertTrue(estr.getJogada()==esperado);
		}
	}
	
	@Test
	public void testaEstrategiaTitForTat(){
		int[] sequencia = {1,0,1,0,0,0,1,0,0,0};
		int[] esperado =  {0,1,0,1,0,0,0,1,0,0};
		EstrategiaTitForTat estr = new EstrategiaTitForTat();
		for (int i = 0; i < sequencia.length; i++) {
			assertTrue(estr.getJogada()==esperado[i]);
			estr.setJogadaAnteriorAdversario(sequencia[i]);
		}
	}
	
	@Test
	public void testaEstrategia2TitForTat(){
		int[] sequencia = {1,0,1,0,0,0,1,0,0,0};
		int[] esperado =  {0,1,1,1,1,0,0,1,1,0};
		EstrategiaTitForTat estr = new EstrategiaTitForTat(2);
		for (int i = 0; i < sequencia.length; i++) {
			assertTrue(estr.getJogada()==esperado[i]);
			estr.setJogadaAnteriorAdversario(sequencia[i]);
		}
	}
	
	@Test
	public void testaEstrategia5TitForTat(){
		int[] sequencia = {1,0,0,0,1,0,0,0,0,0,0};
		int[] esperado =  {0,1,1,1,1,1,1,1,1,1,0};
		EstrategiaTitForTat estr = new EstrategiaTitForTat(5);
		for (int i = 0; i < sequencia.length; i++) {
			assertTrue(estr.getJogada()==esperado[i]);
			estr.setJogadaAnteriorAdversario(sequencia[i]);
		}
	}
	
	@Test
	public void testaEstrategiaMista(){
		double[] estrategia = {0, 0};
		int total = 1000000;
		TabelaPayoffs tabela = TabelaPayoffs.getInstance();
		tabela.selecionarTabela(3);
		EstrategiaMista estr = new EstrategiaMista(0);
		
		for (int i = 0; i < total; i++) {
			estrategia[estr.getJogada()]++;
		}
		assertTrue(((double)estrategia[0]/total)>(0.65) && ((double)estrategia[0]/total)<(0.67));
		assertTrue(((double)estrategia[1]/total)>(0.32) && ((double)estrategia[1]/total)<(0.34));
		
		estr = new EstrategiaMista(1);
		estrategia[0] = estrategia[1] = 0;
		
		for (int i = 0; i < total; i++) {
			estrategia[estr.getJogada()]++;
		}
		assertTrue(((double)estrategia[1]/total)>(0.65) && ((double)estrategia[1]/total)<(0.67));
		assertTrue(((double)estrategia[0]/total)>(0.32) && ((double)estrategia[0]/total)<(0.34));
	}
	
	@Test
	public void testaMaximax(){
		TabelaPayoffs tabela = TabelaPayoffs.getInstance();
		tabela.selecionarTabela(0);
		Estrategia est = new EstrategiaMaximax(0);
		assertTrue(est.getJogada()==1);
	}
	
	@Test
	public void testaMaximin(){
		TabelaPayoffs tabela = TabelaPayoffs.getInstance();
		tabela.selecionarTabela(0);
		Estrategia est = new EstrategiaMaximin(0);
		assertTrue(est.getJogada()==1);
	}
	
}
